Date: Sat Sep 7 13:39:10 2019
Scientist: Ran Yin
Sequencing (Waksman): Dibyendu Kumar
Statistics: Davit Sargsyan
Principal Investigator: Ah-Ng Kong

# Taxonomic Ranks:
# **K**ing **P**hillip **C**an n**O**t **F**ind **G**reen **S**ocks
# * Kingdom                
# * Phylum                    
# * Class                   
# * Order                   
# * Family     
# * Genus     
# * Species  
options(stringsAsFactors = FALSE,
        scipen = 999)
# # Increase mmemory size to 64 Gb----
# invisible(utils::memory.limit(65536))
# str(knitr::opts_chunk$get())
# # NOTE: the below does not work!
# knitr::opts_chunk$set(echo = FALSE, 
#                       message = FALSE,
#                       warning = FALSE,
#                       error = FALSE)
# require(knitr)
# require(kableExtra)
# require(phyloseq)
# require(shiny)
require(data.table)
require(ggplot2)
require(plotly)
require(DT)
source("source/functions_may2019.R")
# On Windows set multithread=FALSE----
mt <- TRUE

1 Introduction

C57BL/6 wild-type (WT) and Nrf-2 double-knock-out (KO -/-) mice were given 2-week microbiome stabilization process using AIN93M diet and 8 more weeks to treat with either AIN93M or AIN93M 5% PEITC diet. Fecal samples were collected weekly, immediately frozen in liquid nitrogen and stored at -80oC. Serum, cecal, colon epithelial and whole colon tissues at week 10 were also collected for further analyses. Baseline, week 1 and 4 fecal samples were selected for 16s rRNA sequencing.

This document examines results from the WT mice samples.

We will attampt to answer the following questions:
1. Did microbiome change over time?
2. Was microbiome affected by diet?
3. Was there a difference between the KO and WT?
4. If there was a change in microbiome composition, what functional changes did it carry? What are the essential functions of the bacteria affected by the treatment and how can this be shown in vivo (metabolites, inflammation markers, etc.)?

2 Data preprocessing

2.1 Raw Data

FastQ files were downloaded from Dr. Kumar’s DropBox. A total of 60 files (2 per sample, pair-ended) and 2 metadata files were downloaded.

2.2 Script

This script (nrf2ubiome_dada2_may2019_v1.Rmd) was developed using DADA2 Pipeline Tutorial (1.12) with tips and tricks from the University of Maryland Shool of Medicine Institute for Genome Sciences (IGS) Microbiome Analysis Workshop (April 8-11, 2019). The output of the DADA2 script (data_may2019/ps_may2019.RData) is explored in this document.

3 Meta data: sample description

# Load data----
# Counts
load("data_may2019/ps_may2019.RData")
# Taxonomy
load("data_may2019/taxa.RData")
taxa <- data.table(seq16s = rownames(taxa),
                   taxa)
# Samples
samples <- ps_may2019@sam_data
datatable(samples,
              options = list(pageLength = nrow(samples)))

4 Prune data

The OTUs were mapped to Bacteria (98.34%), Eukaryota (1.43%) and undefined (0.23%) kingdoms.

The total of 8,129 unique sequences were found. Out of those, 7,994 were mapped to bacterial genomes.

dim(ps_may2019@otu_table@.Data)
[1]   30 8129
# Remove OTU unmapped to Bacteria
ps0 <- subset_taxa(ps_may2019, 
                   Kingdom == "Bacteria")
dim(ps0@otu_table@.Data)
[1]   30 7994

These belonged to 13 Phylum. 230 of the OTUs (or 2.88% of bacterial OTUs) could not be mapped to a Phyla and were removed from this analysis (with 7,764 OTUs left).

t2 <- data.table(table(tax_table(ps0)[, "Phylum"],
                                  exclude = NULL))
t2$V1[is.na(t2$V1)] <- "Unknown"
setorder(t2, -N)
t2[, pct := N/sum(N)]
setorder(t2, -N)
colnames(t2) <- c("Phylum",
                  "Number of OTUs",
                  "Percent of OTUs")
datatable(t2,
          rownames = FALSE,
          caption = "Number of Bacterial OTUs by Phylum",
          class = "cell-border stripe",
          options = list(search = FALSE,
                         pageLength = nrow(t2))) %>%
  formatCurrency(columns = 2,
                 currency = "",
                 mark = ",",
                 digits = 0) %>%
  formatPercentage(columns = 3,
                   digits = 2)

ps1 <- subset_taxa(ps0, 
                   !is.na(Phylum))
dim(ps1@otu_table@.Data)
[1]   30 7764

5 Richness (Alpha diversity)

Shannon’s diversity index was calculated for each sample and ploted over time using the 7,764 from the 13 Phylum above.

ps0@sam_data$Diet_Week <- paste(samples$TREATMENT,
                                samples$WEEK,
                                sep = "_")
ps0@sam_data$ID <- substr(x = ps0@sam_data$SAMPLE_NAME,
                          start = 2,
                          stop = 3)
p1 <- plot_richness(ps0,
                    x = "Diet_Week", 
                    measures = "Shannon") +
    geom_line(aes(group = ID),
            color = "black") +
  geom_point(aes(fill = ID),
             shape = 21,
             size = 3,
             color = "black") +
  scale_x_discrete("") +
  theme(axis.text.x = element_text(angle = 30,
                                   hjust = 1,
                                   vjust = 1))
ggplotly(p = p1,
         tooltip = c("ID",
                     "value"))

p1 <- p1 + theme(legend.position = "none")
tiff(filename = "tmp/wt_shannon.tiff",
     height = 4,
     width = 5,
     units = "in",
     res = 600,
     compression = "lzw+p")
print(p1)
graphics.off()
tmp <- data.table(p1$data)
tmp[, delta := value[WEEK == "week 4"] - 
      value[WEEK == "week 0"],
    by = ID]
tmp1 <- droplevels(unique(tmp[WEEK %in% c("week 0",
                                          "week 4"), 
                              c("value",
                                "WEEK",
                                "TREATMENT")]))
m1 <- lm(value ~ WEEK*TREATMENT,
         data = tmp1)
print("Model1: Shannon's index by treatment and time")
[1] "Model1: Shannon's index by treatment and time"
anova(m1)
Analysis of Variance Table

Response: value
               Df  Sum Sq  Mean Sq F value Pr(>F)
WEEK            1 0.03260 0.032600  0.9415 0.3463
TREATMENT       1 0.00184 0.001836  0.0530 0.8208
WEEK:TREATMENT  1 0.03978 0.039778  1.1487 0.2997
Residuals      16 0.55405 0.034628               
tmp2 <- droplevels(unique(tmp[WEEK == "week 0", 
                              c("delta",
                                "value",
                                "TREATMENT")]))
m2 <- lm(delta ~ TREATMENT,
         data = tmp2)
print("Model2: Shannon's index differences (Week 4 - Week 0) by treatment")
[1] "Model2: Shannon's index differences (Week 4 - Week 0) by treatment"
anova(m2)
Analysis of Variance Table

Response: delta
          Df  Sum Sq  Mean Sq F value Pr(>F)
TREATMENT  1 0.07956 0.079555  1.2057 0.3041
Residuals  8 0.52784 0.065981               
m3 <- wilcox.test(delta ~ TREATMENT,
            data = tmp2)
print("Model3: Wilcoxon test for Shannon's index differences (Week 4 - Week 0) by treatment")
[1] "Model3: Wilcoxon test for Shannon's index differences (Week 4 - Week 0) by treatment"
m3

    Wilcoxon rank sum test

data:  delta by TREATMENT
W = 7, p-value = 0.3095
alternative hypothesis: true location shift is not equal to 0

The results showed that in 4 out of 5 animals in the PEITC group diversity increased over the 4 weeks compared to the baseline. At the same time, only 2 out of 5 Control animals increased its microbial diversity in the same period of time. NOTE: there was no statistically significant difference between the treatment groups as well as over time (see results above).

6 OTU table (first 10 rows)

7 Total counts per sample (i.e. sequencing depth)

8 Counts at Phylum level

9 Relative abundance (%) at Phylum level

Remove phyla with relative abundance of >= 1% in less than 10% of samples.

t1 <- data.table(Phylum = ra_p$Phylum,
                 `Number of Samples` = rowSums(ra_p[, 2:ncol(ra_p)] >= 0.01))
t1$`Percent Samples` <-  t1$`Number of Samples`/30
setorder(t1, -`Number of Samples`)
datatable(t1,
          rownames = FALSE,
          caption = "Taxonomic  count table",
          class = "cell-border stripe",
          options = list(search = FALSE,
                         pageLength = nrow(t1))) %>%
  formatPercentage(columns = 3,
                   digits = 1)

Hence, only 6 out of 13 Phyla were studied in this analysis: Actinobacteria, Bacteroidetes, Firmicutes, Proteobacteria, Tenericutes and Verrucomicrobia. Relative abundance at the next taxonomic level (Class) was, therefore, computed relative to the sum of these 6 Phyla.

[1] "Bacteroidetes, Firmicutes, Proteobacteria, Verrucomicrobia, Actinobacteria, Tenericutes"

7,628 OTUs, down from 7,764 OTUs in the previous table.

10 Relative Abundance in Samples at Different Taxonomic Ranks

10.1 1. Class

p0 <- ggplot(mu,
             aes(x = Week,
                 y = x,
                 group = Treatment)) +
  facet_wrap(~ Class,
             scale = "free_y") +
  geom_line() +
  geom_point(aes(shape = Treatment,
                 color = Treatment),
             size = 3,
             alpha = 0.5) +
  scale_x_discrete("") +
  scale_y_continuous("Relative Abundance (%)") +
  theme(legend.position = "top",
        axis.text.x = element_text(angle = 45,
                                   hjust = 1))
tiff(filename = "tmp/wt_class_over_time.tiff",
     height = 5,
     width = 7,
     units = "in",
     res = 600,
     compression = "lzw+p")
print(p0)
graphics.off()
print(p0)

p1 <- ggplot(mu,
             aes(x = x,
                 y = Class,
                 color = Treatment,
                 shape = Week)) +
  geom_point(size = 3,
             alpha = 0.5) +
  geom_vline(xintercept = 1,
             linetype = "dashed") +
  scale_x_continuous("Relative Abundance (%)") +
  theme(legend.position = "top")
tiff(filename = "tmp/wt_class_ra.tiff",
     height = 4,
     width = 7,
     units = "in",
     res = 600,
     compression = "lzw+p")
print(p1)
graphics.off()
ggplotly(p1)

10.2 2. Order

p0 <- ggplot(mu,
             aes(x = Week,
                 y = x,
                 group = Treatment)) +
  facet_wrap(~ Order,
             scale = "free_y") +
  geom_line() +
  geom_point(aes(shape = Treatment,
                 color = Treatment),
             size = 5,
             alpha = 0.5)
print(p0)
p1 <- ggplot(mu,
             aes(x = x,
                 y = Order,
                 fill = Treatment,
                 shape = Week)) +
  # facet_wrap(~ Sex, nrow = 1) +
  geom_point(size = 3,
             alpha = 0.5) +
  geom_vline(xintercept = 1,
             linetype = "dashed") +
  scale_x_continuous("Relative Abundance (%)")
ggplotly(p1)

11 Session Information

sessionInfo()
LS0tCnRpdGxlOiAiTnJmMiBCTDYgV2lsZC1UeXBlIChXVCkgUEVJVEMgMTZTIE1pY3JvYmlvbWUgRGF0YSBWaXN1YWxpemF0aW9uIgpvdXRwdXQ6IAogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKICAgIG51bWJlcl9zZWN0aW9uczogeWVzCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKLS0tCkRhdGU6IGByIGRhdGUoKWAgICAgIApTY2llbnRpc3Q6IFtSYW4gWWluXShtYWlsdG86cnkxNDdAc2NhcmxldG1haWwucnV0Z2Vycy5lZHUpICAgICAgClNlcXVlbmNpbmcgKFdha3NtYW4pOiBbRGlieWVuZHUgS3VtYXJdKG1haWx0bzpka0B3YWtzbWFuLnJ1dGdlcnMuZWR1KSAgICAgIApTdGF0aXN0aWNzOiBbRGF2aXQgU2FyZ3N5YW5dKG1haWx0bzpzYXJnZGF2aWRAZ21haWwuY29tKSAgICAgIApQcmluY2lwYWwgSW52ZXN0aWdhdG9yOiBbQWgtTmcgS29uZ10obWFpbHRvOmtvbmd0QHBoYXJtYWN5LnJ1dGdlcnMuZWR1KSAKCmBgYHt9CiMgVGF4b25vbWljIFJhbmtzOgojICoqSyoqaW5nICoqUCoqaGlsbGlwICoqQyoqYW4gbioqTyoqdCAqKkYqKmluZCAqKkcqKnJlZW4gKipTKipvY2tzCiMgKiBLaW5nZG9tICAgICAgICAgICAgICAgIAojICogUGh5bHVtICAgICAgICAgICAgICAgICAgICAKIyAqIENsYXNzICAgICAgICAgICAgICAgICAgIAojICogT3JkZXIgICAgICAgICAgICAgICAgICAgCiMgKiBGYW1pbHkgICAgIAojICogR2VudXMgICAgIAojICogU3BlY2llcyAgCmBgYAoKYGBge3Igc2V0dXB9Cm9wdGlvbnMoc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFLAogICAgICAgIHNjaXBlbiA9IDk5OSkKCiMgIyBJbmNyZWFzZSBtbWVtb3J5IHNpemUgdG8gNjQgR2ItLS0tCiMgaW52aXNpYmxlKHV0aWxzOjptZW1vcnkubGltaXQoNjU1MzYpKQoKCiMgc3RyKGtuaXRyOjpvcHRzX2NodW5rJGdldCgpKQojICMgTk9URTogdGhlIGJlbG93IGRvZXMgbm90IHdvcmshCiMga25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBGQUxTRSwgCiMgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBGQUxTRSwKIyAgICAgICAgICAgICAgICAgICAgICAgd2FybmluZyA9IEZBTFNFLAojICAgICAgICAgICAgICAgICAgICAgICBlcnJvciA9IEZBTFNFKQoKIyByZXF1aXJlKGtuaXRyKQojIHJlcXVpcmUoa2FibGVFeHRyYSkKIyByZXF1aXJlKHBoeWxvc2VxKQojIHJlcXVpcmUoc2hpbnkpCgpyZXF1aXJlKGRhdGEudGFibGUpCnJlcXVpcmUoZ2dwbG90MikKcmVxdWlyZShwbG90bHkpCnJlcXVpcmUoRFQpCgpzb3VyY2UoInNvdXJjZS9mdW5jdGlvbnNfbWF5MjAxOS5SIikKCiMgT24gV2luZG93cyBzZXQgbXVsdGl0aHJlYWQ9RkFMU0UtLS0tCm10IDwtIFRSVUUKYGBgCgojIEludHJvZHVjdGlvbgpDNTdCTC82IHdpbGQtdHlwZSAoV1QpIGFuZCBOcmYtMiBkb3VibGUta25vY2stb3V0IChLTyAtLy0pIG1pY2Ugd2VyZSBnaXZlbiAyLXdlZWsgbWljcm9iaW9tZSBzdGFiaWxpemF0aW9uIHByb2Nlc3MgdXNpbmcgQUlOOTNNIGRpZXQgYW5kIDggbW9yZSB3ZWVrcyB0byB0cmVhdCB3aXRoIGVpdGhlciBBSU45M00gb3IgQUlOOTNNIDUlIFBFSVRDIGRpZXQuIEZlY2FsIHNhbXBsZXMgd2VyZSBjb2xsZWN0ZWQgd2Vla2x5LCBpbW1lZGlhdGVseSBmcm96ZW4gaW4gbGlxdWlkIG5pdHJvZ2VuIGFuZCBzdG9yZWQgYXQgLTgwXm9eQy4gU2VydW0sIGNlY2FsLCBjb2xvbiBlcGl0aGVsaWFsIGFuZCB3aG9sZSBjb2xvbiB0aXNzdWVzIGF0IHdlZWsgMTAgd2VyZSBhbHNvIGNvbGxlY3RlZCBmb3IgZnVydGhlciBhbmFseXNlcy4gQmFzZWxpbmUsIHdlZWsgMSBhbmQgNCBmZWNhbCBzYW1wbGVzIHdlcmUgc2VsZWN0ZWQgZm9yIDE2cyByUk5BIHNlcXVlbmNpbmcuICAKICAKVGhpcyBkb2N1bWVudCBleGFtaW5lcyByZXN1bHRzIGZyb20gdGhlIFdUIG1pY2Ugc2FtcGxlcy4gIAogIApXZSB3aWxsIGF0dGFtcHQgdG8gYW5zd2VyIHRoZSBmb2xsb3dpbmcgcXVlc3Rpb25zOiAgCjEuIERpZCBtaWNyb2Jpb21lIGNoYW5nZSBvdmVyIHRpbWU/ICAKMi4gV2FzIG1pY3JvYmlvbWUgYWZmZWN0ZWQgYnkgZGlldD8gIAozLiBXYXMgdGhlcmUgYSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIEtPIGFuZCBXVD8gIAo0LiBJZiB0aGVyZSB3YXMgYSBjaGFuZ2UgaW4gbWljcm9iaW9tZSBjb21wb3NpdGlvbiwgd2hhdCBmdW5jdGlvbmFsIGNoYW5nZXMgZGlkIGl0IGNhcnJ5PyBXaGF0IGFyZSB0aGUgZXNzZW50aWFsIGZ1bmN0aW9ucyBvZiB0aGUgYmFjdGVyaWEgYWZmZWN0ZWQgYnkgdGhlIHRyZWF0bWVudCBhbmQgaG93IGNhbiB0aGlzIGJlIHNob3duIGluIHZpdm8gKG1ldGFib2xpdGVzLCBpbmZsYW1tYXRpb24gbWFya2VycywgZXRjLik/CgojIERhdGEgcHJlcHJvY2Vzc2luZwojIyBSYXcgRGF0YSAKRmFzdFEgZmlsZXMgd2VyZSBkb3dubG9hZGVkIGZyb20gW0RyLiBLdW1hcidzIERyb3BCb3hdKGh0dHBzOi8vd3d3LmRyb3Bib3guY29tL3NoL3NtOXRpbm0wZjVyNnkxdi9BQURqR1BSUk5pSU03ek1TZkFORGtRakZhP2RsPTApLiBBIHRvdGFsIG9mIDYwIGZpbGVzICgyIHBlciBzYW1wbGUsIHBhaXItZW5kZWQpIGFuZCAyIG1ldGFkYXRhIGZpbGVzIHdlcmUgZG93bmxvYWRlZC4KCiMjIFNjcmlwdApUaGlzIHNjcmlwdCAoKioqbnJmMnViaW9tZV9kYWRhMl9tYXkyMDE5X3YxLlJtZCoqKikgd2FzIGRldmVsb3BlZCB1c2luZyBbREFEQTIgUGlwZWxpbmUgVHV0b3JpYWwgKDEuMTIpXShodHRwczovL2JlbmpqbmViLmdpdGh1Yi5pby9kYWRhMi90dXRvcmlhbC5odG1sKSB3aXRoIHRpcHMgYW5kIHRyaWNrcyBmcm9tIHRoZSBbVW5pdmVyc2l0eSBvZiBNYXJ5bGFuZCBTaG9vbCBvZiBNZWRpY2luZSBJbnN0aXR1dGUgZm9yIEdlbm9tZSBTY2llbmNlcyAoSUdTKV0oaHR0cDovL3d3dy5pZ3MudW1hcnlsYW5kLmVkdS8pIFtNaWNyb2Jpb21lIEFuYWx5c2lzIFdvcmtzaG9wIChBcHJpbCA4LTExLCAyMDE5KV0oaHR0cDovL3d3dy5pZ3MudW1hcnlsYW5kLmVkdS9lZHVjYXRpb24vd2tzaHBfbWV0YWdlbm9tZS5waHApLiBUaGUgb3V0cHV0IG9mIHRoZSBEQURBMiBzY3JpcHQgKCoqKmRhdGFfbWF5MjAxOS9wc19tYXkyMDE5LlJEYXRhKioqKSBpcyBleHBsb3JlZCBpbiB0aGlzIGRvY3VtZW50LgoKIyBNZXRhIGRhdGE6IHNhbXBsZSBkZXNjcmlwdGlvbgpgYGB7ciBkYXRhfQojIExvYWQgZGF0YS0tLS0KIyBDb3VudHMKbG9hZCgiZGF0YV9tYXkyMDE5L3BzX21heTIwMTkuUkRhdGEiKQoKIyBUYXhvbm9teQpsb2FkKCJkYXRhX21heTIwMTkvdGF4YS5SRGF0YSIpCnRheGEgPC0gZGF0YS50YWJsZShzZXExNnMgPSByb3duYW1lcyh0YXhhKSwKICAgICAgICAgICAgICAgICAgIHRheGEpCgojIFNhbXBsZXMKc2FtcGxlcyA8LSBwc19tYXkyMDE5QHNhbV9kYXRhCmRhdGF0YWJsZShzYW1wbGVzLAogICAgICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KHBhZ2VMZW5ndGggPSBucm93KHNhbXBsZXMpKSkKYGBgCgojIFBydW5lIGRhdGEKVGhlIE9UVXMgd2VyZSBtYXBwZWQgdG8gQmFjdGVyaWEgKDk4LjM0JSksIEV1a2FyeW90YSAoMS40MyUpIGFuZCB1bmRlZmluZWQgKDAuMjMlKSBraW5nZG9tcy4gCgpgYGB7ciBjaGVja19tYXBwaW5nX2tpbmdkb20sIHdhcm5pbmcgPSBGQUxTRSwgZWNobyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0V9CnQxIDwtIGRhdGEudGFibGUodGFibGUodGF4X3RhYmxlKHBzX21heTIwMTkpWywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIktpbmdkb20iXSwKICAgICAgICAgICAgICAgICAgICAgICBleGNsdWRlID0gTlVMTCkpCnQxJFYxW2lzLm5hKHQxJFYxKV0gPC0gIlVua25vd24iCgp0MVssIHBjdCA6PSBOL3N1bShOKV0Kc2V0b3JkZXIodDEsIC1OKQoKY29sbmFtZXModDEpIDwtIGMoIktpbmdkb20iLAogICAgICAgICAgICAgICAgICAiTnVtYmVyIG9mIE9UVXMiLAogICAgICAgICAgICAgICAgICAiUGVyY2VudCBvZiBPVFVzIikKZGF0YXRhYmxlKHQxLAogICAgICAgICAgcm93bmFtZXMgPSBGQUxTRSwKICAgICAgICAgIGNhcHRpb24gPSAiTnVtYmVyIG9mIE9UVXMgYnkgS2luZ2RvbSIsCiAgICAgICAgICBjbGFzcyA9ICJjZWxsLWJvcmRlciBzdHJpcGUiLAogICAgICAgICAgb3B0aW9ucyA9IGxpc3Qoc2VhcmNoID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICBwYWdlTGVuZ3RoID0gbnJvdyh0MSkpKSAlPiUKICBmb3JtYXRDdXJyZW5jeShjb2x1bW5zID0gMiwKICAgICAgICAgICAgICAgICBjdXJyZW5jeSA9ICIiLAogICAgICAgICAgICAgICAgIG1hcmsgPSAiLCIsCiAgICAgICAgICAgICAgICAgZGlnaXRzID0gMCkgJT4lCiAgZm9ybWF0UGVyY2VudGFnZShjb2x1bW5zID0gMywKICAgICAgICAgICAgICAgICAgIGRpZ2l0cyA9IDIpCmBgYAoKVGhlIHRvdGFsIG9mIDgsMTI5IHVuaXF1ZSBzZXF1ZW5jZXMgd2VyZSBmb3VuZC4gT3V0IG9mIHRob3NlLCA3LDk5NCB3ZXJlIG1hcHBlZCB0byBiYWN0ZXJpYWwgZ2Vub21lcy4gCgpgYGB7ciBrZWVwX2JhY3RlcmlhfQpkaW0ocHNfbWF5MjAxOUBvdHVfdGFibGVALkRhdGEpCgojIFJlbW92ZSBPVFUgdW5tYXBwZWQgdG8gQmFjdGVyaWEKcHMwIDwtIHN1YnNldF90YXhhKHBzX21heTIwMTksIAogICAgICAgICAgICAgICAgICAgS2luZ2RvbSA9PSAiQmFjdGVyaWEiKQpkaW0ocHMwQG90dV90YWJsZUAuRGF0YSkKYGBgCiAgClRoZXNlIGJlbG9uZ2VkIHRvIDEzIFBoeWx1bS4gMjMwIG9mIHRoZSBPVFVzIChvciAyLjg4JSBvZiBiYWN0ZXJpYWwgT1RVcykgY291bGQgbm90IGJlIG1hcHBlZCB0byBhIFBoeWxhIGFuZCB3ZXJlIHJlbW92ZWQgZnJvbSB0aGlzIGFuYWx5c2lzICh3aXRoIDcsNzY0IE9UVXMgbGVmdCkuCgpgYGB7ciBwaHlsdW1fbWFwcGluZ30KdDIgPC0gZGF0YS50YWJsZSh0YWJsZSh0YXhfdGFibGUocHMwKVssICJQaHlsdW0iXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2x1ZGUgPSBOVUxMKSkKdDIkVjFbaXMubmEodDIkVjEpXSA8LSAiVW5rbm93biIKc2V0b3JkZXIodDIsIC1OKQp0MlssIHBjdCA6PSBOL3N1bShOKV0Kc2V0b3JkZXIodDIsIC1OKQoKY29sbmFtZXModDIpIDwtIGMoIlBoeWx1bSIsCiAgICAgICAgICAgICAgICAgICJOdW1iZXIgb2YgT1RVcyIsCiAgICAgICAgICAgICAgICAgICJQZXJjZW50IG9mIE9UVXMiKQoKZGF0YXRhYmxlKHQyLAogICAgICAgICAgcm93bmFtZXMgPSBGQUxTRSwKICAgICAgICAgIGNhcHRpb24gPSAiTnVtYmVyIG9mIEJhY3RlcmlhbCBPVFVzIGJ5IFBoeWx1bSIsCiAgICAgICAgICBjbGFzcyA9ICJjZWxsLWJvcmRlciBzdHJpcGUiLAogICAgICAgICAgb3B0aW9ucyA9IGxpc3Qoc2VhcmNoID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICBwYWdlTGVuZ3RoID0gbnJvdyh0MikpKSAlPiUKICBmb3JtYXRDdXJyZW5jeShjb2x1bW5zID0gMiwKICAgICAgICAgICAgICAgICBjdXJyZW5jeSA9ICIiLAogICAgICAgICAgICAgICAgIG1hcmsgPSAiLCIsCiAgICAgICAgICAgICAgICAgZGlnaXRzID0gMCkgJT4lCiAgZm9ybWF0UGVyY2VudGFnZShjb2x1bW5zID0gMywKICAgICAgICAgICAgICAgICAgIGRpZ2l0cyA9IDIpCgpwczEgPC0gc3Vic2V0X3RheGEocHMwLCAKICAgICAgICAgICAgICAgICAgICFpcy5uYShQaHlsdW0pKQpkaW0ocHMxQG90dV90YWJsZUAuRGF0YSkKYGBgCgojIFJpY2huZXNzIChBbHBoYSBkaXZlcnNpdHkpClNoYW5ub24ncyBkaXZlcnNpdHkgaW5kZXggd2FzIGNhbGN1bGF0ZWQgZm9yIGVhY2ggc2FtcGxlIGFuZCBwbG90ZWQgb3ZlciB0aW1lIHVzaW5nIHRoZSA3LDc2NCBmcm9tIHRoZSAxMyBQaHlsdW0gYWJvdmUuCgpgYGB7ciByaWNobmVzcywgZmlnLndpZHRoID0gMTAsZmlnLmhlaWdodCA9IDV9CnBzMEBzYW1fZGF0YSREaWV0X1dlZWsgPC0gcGFzdGUoc2FtcGxlcyRUUkVBVE1FTlQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlcyRXRUVLLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcCA9ICJfIikKcHMwQHNhbV9kYXRhJElEIDwtIHN1YnN0cih4ID0gcHMwQHNhbV9kYXRhJFNBTVBMRV9OQU1FLAogICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXJ0ID0gMiwKICAgICAgICAgICAgICAgICAgICAgICAgICBzdG9wID0gMykKcDEgPC0gcGxvdF9yaWNobmVzcyhwczAsCiAgICAgICAgICAgICAgICAgICAgeCA9ICJEaWV0X1dlZWsiLCAKICAgICAgICAgICAgICAgICAgICBtZWFzdXJlcyA9ICJTaGFubm9uIikgKwogICAgZ2VvbV9saW5lKGFlcyhncm91cCA9IElEKSwKICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siKSArCiAgZ2VvbV9wb2ludChhZXMoZmlsbCA9IElEKSwKICAgICAgICAgICAgIHNoYXBlID0gMjEsCiAgICAgICAgICAgICBzaXplID0gMywKICAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIikgKwogIHNjYWxlX3hfZGlzY3JldGUoIiIpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDMwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhqdXN0ID0gMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2anVzdCA9IDEpKQoKZ2dwbG90bHkocCA9IHAxLAogICAgICAgICB0b29sdGlwID0gYygiSUQiLAogICAgICAgICAgICAgICAgICAgICAidmFsdWUiKSkKCnAxIDwtIHAxICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQoKdGlmZihmaWxlbmFtZSA9ICJ0bXAvd3Rfc2hhbm5vbi50aWZmIiwKICAgICBoZWlnaHQgPSA0LAogICAgIHdpZHRoID0gNSwKICAgICB1bml0cyA9ICJpbiIsCiAgICAgcmVzID0gNjAwLAogICAgIGNvbXByZXNzaW9uID0gImx6dytwIikKcHJpbnQocDEpCmdyYXBoaWNzLm9mZigpCmBgYAoKYGBge3IgdGVzdF9yaWNobmVzc30KdG1wIDwtIGRhdGEudGFibGUocDEkZGF0YSkKdG1wWywgZGVsdGEgOj0gdmFsdWVbV0VFSyA9PSAid2VlayA0Il0gLSAKICAgICAgdmFsdWVbV0VFSyA9PSAid2VlayAwIl0sCiAgICBieSA9IElEXQoKdG1wMSA8LSBkcm9wbGV2ZWxzKHVuaXF1ZSh0bXBbV0VFSyAlaW4lIGMoIndlZWsgMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJ3ZWVrIDQiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMoInZhbHVlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiV0VFSyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlRSRUFUTUVOVCIpXSkpCm0xIDwtIGxtKHZhbHVlIH4gV0VFSypUUkVBVE1FTlQsCiAgICAgICAgIGRhdGEgPSB0bXAxKQpwcmludCgiTW9kZWwxOiBTaGFubm9uJ3MgaW5kZXggYnkgdHJlYXRtZW50IGFuZCB0aW1lIikKYW5vdmEobTEpCgp0bXAyIDwtIGRyb3BsZXZlbHModW5pcXVlKHRtcFtXRUVLID09ICJ3ZWVrIDAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYygiZGVsdGEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJ2YWx1ZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlRSRUFUTUVOVCIpXSkpCm0yIDwtIGxtKGRlbHRhIH4gVFJFQVRNRU5ULAogICAgICAgICBkYXRhID0gdG1wMikKcHJpbnQoIk1vZGVsMjogU2hhbm5vbidzIGluZGV4IGRpZmZlcmVuY2VzIChXZWVrIDQgLSBXZWVrIDApIGJ5IHRyZWF0bWVudCIpCmFub3ZhKG0yKQoKbTMgPC0gd2lsY294LnRlc3QoZGVsdGEgfiBUUkVBVE1FTlQsCiAgICAgICAgICAgIGRhdGEgPSB0bXAyKQpwcmludCgiTW9kZWwzOiBXaWxjb3hvbiB0ZXN0IGZvciBTaGFubm9uJ3MgaW5kZXggZGlmZmVyZW5jZXMgKFdlZWsgNCAtIFdlZWsgMCkgYnkgdHJlYXRtZW50IikKbTMKYGBgCiAgClRoZSByZXN1bHRzIHNob3dlZCB0aGF0IGluIDQgb3V0IG9mIDUgYW5pbWFscyBpbiB0aGUgUEVJVEMgZ3JvdXAgZGl2ZXJzaXR5IGluY3JlYXNlZCBvdmVyIHRoZSA0IHdlZWtzIGNvbXBhcmVkIHRvIHRoZSBiYXNlbGluZS4gQXQgdGhlIHNhbWUgdGltZSwgb25seSAyIG91dCBvZiA1IENvbnRyb2wgYW5pbWFscyBpbmNyZWFzZWQgaXRzIG1pY3JvYmlhbCBkaXZlcnNpdHkgaW4gdGhlIHNhbWUgcGVyaW9kIG9mIHRpbWUuIE5PVEU6IHRoZXJlIHdhcyBubyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgdHJlYXRtZW50IGdyb3VwcyBhcyB3ZWxsIGFzIG92ZXIgdGltZSAoc2VlIHJlc3VsdHMgYWJvdmUpLiAgCiAgCiMgT1RVIHRhYmxlIChmaXJzdCAxMCByb3dzKQpgYGB7ciBvdHVfdGFibGUsIHdhcm5pbmc9RkFMU0UsZWNobz1GQUxTRSxtZXNzYWdlPUZBTFNFfQpvdHUgPC0gZGF0YS50YWJsZShwczBAdGF4X3RhYmxlQC5EYXRhLAogICAgICAgICAgICAgICAgICB0KHBzMEBvdHVfdGFibGVALkRhdGEpKQpkYXRhdGFibGUoaGVhZChvdHUsIDEwKSwKICAgICAgICAgIHJvd25hbWVzID0gRkFMU0UsCiAgICAgICAgICBjYXB0aW9uID0gIlRheG9ub21pYyAgY291bnQgdGFibGUiLAogICAgICAgICAgY2xhc3MgPSAiY2VsbC1ib3JkZXIgc3RyaXBlIiwKICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KHNlYXJjaCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgcGFnZUxlbmd0aCA9IDEwKSkgJT4lCiAgZm9ybWF0Q3VycmVuY3koY29sdW1ucyA9IDc6MzYsCiAgICAgICAgICAgICAgICAgY3VycmVuY3kgPSAiIiwKICAgICAgICAgICAgICAgICBtYXJrID0gIiwiLAogICAgICAgICAgICAgICAgIGRpZ2l0cyA9IDApCmBgYAoKIyBUb3RhbCBjb3VudHMgcGVyIHNhbXBsZSAoaS5lLiBzZXF1ZW5jaW5nIGRlcHRoKQpgYGB7ciBUYXgsIHdhcm5pbmc9RkFMU0UsZWNobz1GQUxTRSxtZXNzYWdlPUZBTFNFLGZpZy53aWR0aD0xMCxmaWcuaGVpZ2h0PTV9CnQxIDwtIGNvbFN1bXMob3R1WywgNzpuY29sKG90dSldKQp0MSA8LSBkYXRhLnRhYmxlKFNBTVBMRV9OQU1FID0gbmFtZXModDEpLAogICAgICAgICAgICAgICAgIFRvdGFsID0gdDEpCgp0bXAgPC0gZGF0YS50YWJsZShTQU1QTEVfTkFNRSA9IHNhbXBsZXMkU0FNUExFX05BTUUsCiAgICAgICAgICAgICAgICAgIFRSRUFUTUVOVCA9IHNhbXBsZXMkVFJFQVRNRU5ULAogICAgICAgICAgICAgICAgICBXRUVLID0gc2FtcGxlcyRXRUVLKQoKdDEgPC0gbWVyZ2UodG1wLAogICAgICAgICAgICB0MSwKICAgICAgICAgICAgYnkgPSAiU0FNUExFX05BTUUiKQoKcDEgPC0gZ2dwbG90KHQxLAogICAgICAgICAgICAgYWVzKHggPSBTQU1QTEVfTkFNRSwKICAgICAgICAgICAgICAgICB5ID0gVG90YWwsCiAgICAgICAgICAgICAgICAgZmlsbCA9IFRSRUFUTUVOVCwKICAgICAgICAgICAgICAgICBjb2xvdXIgPSBXRUVLKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgc2NhbGVfeF9kaXNjcmV0ZSgiU2FtcGxlIE5hbWUiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKCJOdW1iZXIgb2YgUmVhZHMiKSArCiAgc2NhbGVfZmlsbF9kaXNjcmV0ZSgiR3JvdXAiKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoanVzdCA9IDEpKSAKZ2dwbG90bHkocDEpCmBgYAoKIyBDb3VudHMgYXQgUGh5bHVtIGxldmVsCmBgYHtyIGNvdW50c19wLCB3YXJuaW5nPUZBTFNFLGVjaG89RkFMU0UsbWVzc2FnZT1GQUxTRX0KY291bnRzX3AgPC0gY291bnRzX2J5X3RheF9yYW5rKGR0MSA9IG90dSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFnZ3JfYnkgPSAiUGh5bHVtIikKc2V0b3JkZXIoY291bnRzX3AsIC1gMEExYCkKZGF0YXRhYmxlKGNvdW50c19wLAogICAgICAgICAgcm93bmFtZXMgPSBGQUxTRSwKICAgICAgICAgIGNhcHRpb24gPSAiVGF4b25vbWljICBjb3VudCB0YWJsZSIsCiAgICAgICAgICBjbGFzcyA9ICJjZWxsLWJvcmRlciBzdHJpcGUiLAogICAgICAgICAgb3B0aW9ucyA9IGxpc3Qoc2VhcmNoID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICBwYWdlTGVuZ3RoID0gbnJvdyhjb3VudHNfcCkpKSAlPiUKICBmb3JtYXRDdXJyZW5jeShjb2x1bW5zID0gMjpuY29sKGNvdW50c19wKSwKICAgICAgICAgICAgICAgICBjdXJyZW5jeSA9ICIiLAogICAgICAgICAgICAgICAgIG1hcmsgPSAiLCIsCiAgICAgICAgICAgICAgICAgZGlnaXRzID0gMCkKYGBgCgojIFJlbGF0aXZlIGFidW5kYW5jZSAoJSkgYXQgUGh5bHVtIGxldmVsCmBgYHtyIHJhX3AsIHdhcm5pbmc9RkFMU0UsZWNobz1GQUxTRSxtZXNzYWdlPUZBTFNFfQpyYV9wIDwtIHJhX2J5X3RheF9yYW5rKGNvdW50cyA9IGNvdW50c19wLAogICAgICAgICAgICAgICAgICAgICAgIHBjdCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgIGRpZ2l0ID0gNCkKCmRhdGF0YWJsZShyYV9wLAogICAgICAgICAgcm93bmFtZXMgPSBGQUxTRSwKICAgICAgICAgIGNhcHRpb24gPSAiVGF4b25vbWljICBjb3VudCB0YWJsZSIsCiAgICAgICAgICBjbGFzcyA9ICJjZWxsLWJvcmRlciBzdHJpcGUiLAogICAgICAgICAgb3B0aW9ucyA9IGxpc3Qoc2VhcmNoID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICBwYWdlTGVuZ3RoID0gbnJvdyhyYV9wKSkpICU+JQogIGZvcm1hdFBlcmNlbnRhZ2UoY29sdW1ucyA9IDI6bmNvbChjb3VudHNfcCksCiAgICAgICAgICAgICAgICAgICBkaWdpdHMgPSAyKQpgYGAKClJlbW92ZSBwaHlsYSB3aXRoIHJlbGF0aXZlIGFidW5kYW5jZSBvZiA+PSAxJSBpbiBsZXNzIHRoYW4gMTAlIG9mIHNhbXBsZXMuCgpgYGB7ciBwcmV2X3B9CnQxIDwtIGRhdGEudGFibGUoUGh5bHVtID0gcmFfcCRQaHlsdW0sCiAgICAgICAgICAgICAgICAgYE51bWJlciBvZiBTYW1wbGVzYCA9IHJvd1N1bXMocmFfcFssIDI6bmNvbChyYV9wKV0gPj0gMC4wMSkpCnQxJGBQZXJjZW50IFNhbXBsZXNgIDwtICB0MSRgTnVtYmVyIG9mIFNhbXBsZXNgLzMwCgpzZXRvcmRlcih0MSwgLWBOdW1iZXIgb2YgU2FtcGxlc2ApCmRhdGF0YWJsZSh0MSwKICAgICAgICAgIHJvd25hbWVzID0gRkFMU0UsCiAgICAgICAgICBjYXB0aW9uID0gIlRheG9ub21pYyAgY291bnQgdGFibGUiLAogICAgICAgICAgY2xhc3MgPSAiY2VsbC1ib3JkZXIgc3RyaXBlIiwKICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KHNlYXJjaCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgcGFnZUxlbmd0aCA9IG5yb3codDEpKSkgJT4lCiAgZm9ybWF0UGVyY2VudGFnZShjb2x1bW5zID0gMywKICAgICAgICAgICAgICAgICAgIGRpZ2l0cyA9IDEpCmBgYAoKSGVuY2UsIG9ubHkgNiBvdXQgb2YgMTMgUGh5bGEgd2VyZSBzdHVkaWVkIGluIHRoaXMgYW5hbHlzaXM6IEFjdGlub2JhY3RlcmlhLCBCYWN0ZXJvaWRldGVzLCBGaXJtaWN1dGVzLCBQcm90ZW9iYWN0ZXJpYSwgVGVuZXJpY3V0ZXMgYW5kIFZlcnJ1Y29taWNyb2JpYS4gUmVsYXRpdmUgYWJ1bmRhbmNlIGF0IHRoZSBuZXh0IHRheG9ub21pYyBsZXZlbCAoQ2xhc3MpIHdhcywgdGhlcmVmb3JlLCBjb21wdXRlZCByZWxhdGl2ZSB0byB0aGUgc3VtIG9mIHRoZXNlIDYgUGh5bGEuCgpgYGB7ciBrZWVwXzZfcGh5bGEsIHdhcm5pbmc9RkFMU0UsZWNobz1GQUxTRSxtZXNzYWdlPUZBTFNFfQprZWVwX3AgPC0gdDEkUGh5bHVtW3QxJGBQZXJjZW50IFNhbXBsZXNgID49IDAuMV0KcGFzdGUwKGtlZXBfcCwgY29sbGFwc2UgPSAiLCAiKQoKcHMxIDwtIHN1YnNldF90YXhhKHBzMCwgCiAgICAgICAgICAgICAgICAgICBQaHlsdW0gJWluJSBrZWVwX3AgKQpvdHUxIDwtIGRhdGEudGFibGUocHMxQHRheF90YWJsZUAuRGF0YSwKICAgICAgICAgICAgICAgICAgIHQocHMxQG90dV90YWJsZUAuRGF0YSkpCgpkYXRhdGFibGUoaGVhZChvdHUxLCAxMCksCiAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLAogICAgICAgICAgY2FwdGlvbiA9ICJUYXhvbm9taWMgIGNvdW50IHRhYmxlIiwKICAgICAgICAgIGNsYXNzID0gImNlbGwtYm9yZGVyIHN0cmlwZSIsCiAgICAgICAgICBvcHRpb25zID0gbGlzdChzZWFyY2ggPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VMZW5ndGggPSAxMCkpICU+JQogIGZvcm1hdEN1cnJlbmN5KGNvbHVtbnMgPSA3Om5jb2wob3R1MSksCiAgICAgICAgICAgICAgICAgY3VycmVuY3kgPSAiIiwKICAgICAgICAgICAgICAgICBtYXJrID0gIiwiLAogICAgICAgICAgICAgICAgIGRpZ2l0cyA9IDApCmBgYAoKNyw2MjggT1RVcywgZG93biBmcm9tIDcsNzY0IE9UVXMgaW4gdGhlIHByZXZpb3VzIHRhYmxlLgoKCiMgUmVsYXRpdmUgQWJ1bmRhbmNlIGluIFNhbXBsZXMgYXQgRGlmZmVyZW50IFRheG9ub21pYyBSYW5rcwojIyAxLiBDbGFzcwpgYGB7ciBjb3VudHNfYywgd2FybmluZz1GQUxTRSxlY2hvPUZBTFNFLG1lc3NhZ2U9RkFMU0UsZmlnLndpZHRoPTEwLGZpZy5oZWlnaHQ9Nn0KY291bnRzX2MgPC0gY291bnRzX2J5X3RheF9yYW5rKGR0MSA9IG90dTEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZ2dyX2J5ID0gIkNsYXNzIikKcmFfYyA8LSByYV9ieV90YXhfcmFuayhjb3VudHNfYykKCnRheC5yYW5rcyA8LSB1bmlxdWUob3R1MVssIGMoIlBoeWx1bSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNsYXNzIildKQoKcmFfYyA8LSBtZXJnZSh0YXgucmFua3MsCiAgICAgICAgICAgICAgcmFfYywKICAgICAgICAgICAgICBieSA9ICJDbGFzcyIpCgp0b3RhbCA8LSByb3dTdW1zKHJhX2NbLCAzOm5jb2wocmFfYyldKQoKcmFfYyRDbGFzcyA8LSBmYWN0b3IocmFfYyRDbGFzcywKICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gcmFfYyRDbGFzc1tvcmRlcih0b3RhbCldKQoKcmFfYyRQaHlsdW0gPC0gZmFjdG9yKHJhX2MkUGh5bHVtLAogICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gdW5pcXVlKHJhX2MkUGh5bHVtW29yZGVyKHRvdGFsKV0pKQp0bXAgPC0gbWVsdC5kYXRhLnRhYmxlKGRhdGEgPSByYV9jLAogICAgICAgICAgICAgICAgICAgICAgIGlkLnZhcnMgPSAxOjIsCiAgICAgICAgICAgICAgICAgICAgICAgbWVhc3VyZS52YXJzID0gMzpuY29sKGNvdW50c19jKSwKICAgICAgICAgICAgICAgICAgICAgICB2YXJpYWJsZS5uYW1lID0gIlNBTVBMRV9OQU1FIiwKICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZS5uYW1lID0gIlJBIikKCnRtcCA8LSBtZXJnZShkYXRhLnRhYmxlKFNBTVBMRV9OQU1FID0gc2FtcGxlcyRTQU1QTEVfTkFNRSwKICAgICAgICAgICAgICAgICAgICAgICAgV0VFSyA9IHNhbXBsZXMkV0VFSywKICAgICAgICAgICAgICAgICAgICAgICAgVFJFQVRNRU5UID0gc2FtcGxlcyRUUkVBVE1FTlQpLAogICAgICAgICAgICAgdG1wLAogICAgICAgICAgICAgYnkgPSAiU0FNUExFX05BTUUiKQoKIyBQbG90IHNhbXBsZXMKcDEgPC0gZ2dwbG90KHRtcCwKICAgICAgICAgICAgIGFlcyh4ID0gU0FNUExFX05BTUUsCiAgICAgICAgICAgICAgICAgeSA9IFJBLAogICAgICAgICAgICAgICAgIGZpbGwgPSBDbGFzcywKICAgICAgICAgICAgICAgICBjb2xvciA9IFBoeWx1bSkpICsKICBmYWNldF93cmFwKH4gV0VFSyArIFRSRUFUTUVOVCwKICAgICAgICAgICAgIHNjYWxlcyA9ICJmcmVlX3giLAogICAgICAgICAgICAgbnJvdyA9IDMpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogIHNjYWxlX3hfZGlzY3JldGUoIiIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kID0gYygwLCAwKSkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoanVzdCA9IDEpKQpnZ3Bsb3RseShwMSkKYGBgCgpgYGB7ciBtZWFuc19jLCBlY2hvID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFfQpscmEgPC0gcmFfbWVsdChyYSA9IHJhX2MsCiAgICAgICAgICAgICAgIHNhbXBsZXMgPSBzYW1wbGVzLAogICAgICAgICAgICAgICBzYW1wbGVfbmFtZSA9ICJTQU1QTEVfTkFNRSIpCgptdSA8LSBkYXRhLnRhYmxlKGFnZ3JlZ2F0ZShscmEkUkEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gbGlzdChXZWVrID0gbHJhJFdFRUssCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmVhdG1lbnQgPSBscmEkVFJFQVRNRU5ULAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ2xhc3MgPSBscmEkQ2xhc3MpLAogICAgICAgICAgICAgICAgICAgICAgICAgICBGVU4gPSAibWVhbiIpKQptdVssIHRvdGFsIDo9IHN1bSh4KSwKICAgYnkgPSAiQ2xhc3MiXQp1bCA8LSB1bmlxdWUobXVbLCBjKCJDbGFzcyIsIAogICAgICAgICAgICAgICAgICAgICJ0b3RhbCIpXSkKdWwgPC0gdWxbb3JkZXIodG90YWwpLF0KbXUkQ2xhc3MgPC0gZmFjdG9yKG11JENsYXNzLAogICAgICAgICAgICAgICAgICAgbGV2ZWwgPSB1bCRDbGFzcykKbXUkdG90YWwgPC0gTlVMTAoKZGF0YXRhYmxlKG11LAogICAgICAgICAgcm93bmFtZXMgPSBGQUxTRSwKICAgICAgICAgIGNhcHRpb24gPSAiVGF4b25vbWljICBjb3VudCB0YWJsZSIsCiAgICAgICAgICBjbGFzcyA9ICJjZWxsLWJvcmRlciBzdHJpcGUiLAogICAgICAgICAgb3B0aW9ucyA9IGxpc3Qoc2VhcmNoID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICBwYWdlTGVuZ3RoID0gbnJvdyhtdSksCiAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IGxpc3QobGlzdCgzLCAnZGVzYycpKSkpCmBgYAoKCmBgYHtyIG1lYW5zX2NfcDAsIGZpZy53aWR0aCA9IDcsIGZpZy5oZWlnaHQgPSA1fQpwMCA8LSBnZ3Bsb3QobXUsCiAgICAgICAgICAgICBhZXMoeCA9IFdlZWssCiAgICAgICAgICAgICAgICAgeSA9IHgsCiAgICAgICAgICAgICAgICAgZ3JvdXAgPSBUcmVhdG1lbnQpKSArCiAgZmFjZXRfd3JhcCh+IENsYXNzLAogICAgICAgICAgICAgc2NhbGUgPSAiZnJlZV95IikgKwogIGdlb21fbGluZSgpICsKICBnZW9tX3BvaW50KGFlcyhzaGFwZSA9IFRyZWF0bWVudCwKICAgICAgICAgICAgICAgICBjb2xvciA9IFRyZWF0bWVudCksCiAgICAgICAgICAgICBzaXplID0gMywKICAgICAgICAgICAgIGFscGhhID0gMC41KSArCiAgc2NhbGVfeF9kaXNjcmV0ZSgiIikgKwogIHNjYWxlX3lfY29udGludW91cygiUmVsYXRpdmUgQWJ1bmRhbmNlICglKSIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIiwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhqdXN0ID0gMSkpCgp0aWZmKGZpbGVuYW1lID0gInRtcC93dF9jbGFzc19vdmVyX3RpbWUudGlmZiIsCiAgICAgaGVpZ2h0ID0gNSwKICAgICB3aWR0aCA9IDcsCiAgICAgdW5pdHMgPSAiaW4iLAogICAgIHJlcyA9IDYwMCwKICAgICBjb21wcmVzc2lvbiA9ICJsencrcCIpCnByaW50KHAwKQpncmFwaGljcy5vZmYoKQoKcHJpbnQocDApCmBgYAoKCmBgYHtyIG1lYW5zX2NfcDEsIGZpZy5oZWlnaHQgPSA1LCBmaWcud2lkdGggPSA2fQpwMSA8LSBnZ3Bsb3QobXUsCiAgICAgICAgICAgICBhZXMoeCA9IHgsCiAgICAgICAgICAgICAgICAgeSA9IENsYXNzLAogICAgICAgICAgICAgICAgIGNvbG9yID0gVHJlYXRtZW50LAogICAgICAgICAgICAgICAgIHNoYXBlID0gV2VlaykpICsKICBnZW9tX3BvaW50KHNpemUgPSAzLAogICAgICAgICAgICAgYWxwaGEgPSAwLjUpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAxLAogICAgICAgICAgICAgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogIHNjYWxlX3hfY29udGludW91cygiUmVsYXRpdmUgQWJ1bmRhbmNlICglKSIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIikKCnRpZmYoZmlsZW5hbWUgPSAidG1wL3d0X2NsYXNzX3JhLnRpZmYiLAogICAgIGhlaWdodCA9IDQsCiAgICAgd2lkdGggPSA3LAogICAgIHVuaXRzID0gImluIiwKICAgICByZXMgPSA2MDAsCiAgICAgY29tcHJlc3Npb24gPSAibHp3K3AiKQpwcmludChwMSkKZ3JhcGhpY3Mub2ZmKCkKCmdncGxvdGx5KHAxKQpgYGAKCiMjIDIuIE9yZGVyCmBgYHtyIGNvdW50c19vLCB3YXJuaW5nPUZBTFNFLGVjaG89RkFMU0UsbWVzc2FnZT1GQUxTRSxmaWcud2lkdGg9MTAsZmlnLmhlaWdodD02fQpjb3VudHNfbyA8LSBjb3VudHNfYnlfdGF4X3JhbmsoZHQxID0gb3R1MSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFnZ3JfYnkgPSAiT3JkZXIiKQpyYV9vIDwtIHJhX2J5X3RheF9yYW5rKGNvdW50c19vKQoKdGF4LnJhbmtzIDwtIHVuaXF1ZShvdHUxWywgYygiUGh5bHVtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiT3JkZXIiKV0pCgpyYV9vIDwtIG1lcmdlKHRheC5yYW5rcywKICAgICAgICAgICAgICByYV9vLAogICAgICAgICAgICAgIGJ5ID0gIk9yZGVyIikKCnRvdGFsIDwtIHJvd1N1bXMocmFfb1ssIDM6bmNvbChyYV9vKV0pCgpyYV9vJE9yZGVyIDwtIGZhY3RvcihyYV9vJE9yZGVyLAogICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSByYV9vJE9yZGVyW29yZGVyKHRvdGFsKV0pCgpyYV9vJFBoeWx1bSA8LSBmYWN0b3IocmFfbyRQaHlsdW0sCiAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSB1bmlxdWUocmFfbyRQaHlsdW1bb3JkZXIodG90YWwpXSkpCnRtcCA8LSBtZWx0LmRhdGEudGFibGUoZGF0YSA9IHJhX28sCiAgICAgICAgICAgICAgICAgICAgICAgaWQudmFycyA9IDE6MiwKICAgICAgICAgICAgICAgICAgICAgICBtZWFzdXJlLnZhcnMgPSAzOm5jb2woY291bnRzX28pLAogICAgICAgICAgICAgICAgICAgICAgIHZhcmlhYmxlLm5hbWUgPSAiU0FNUExFX05BTUUiLAogICAgICAgICAgICAgICAgICAgICAgIHZhbHVlLm5hbWUgPSAiUkEiKQoKdG1wIDwtIG1lcmdlKGRhdGEudGFibGUoU0FNUExFX05BTUUgPSBzYW1wbGVzJFNBTVBMRV9OQU1FLAogICAgICAgICAgICAgICAgICAgICAgICBXRUVLID0gc2FtcGxlcyRXRUVLLAogICAgICAgICAgICAgICAgICAgICAgICBUUkVBVE1FTlQgPSBzYW1wbGVzJFRSRUFUTUVOVCksCiAgICAgICAgICAgICB0bXAsCiAgICAgICAgICAgICBieSA9ICJTQU1QTEVfTkFNRSIpCgojIFBsb3Qgc2FtcGxlcwpwMSA8LSBnZ3Bsb3QodG1wLAogICAgICAgICAgICAgYWVzKHggPSBTQU1QTEVfTkFNRSwKICAgICAgICAgICAgICAgICB5ID0gUkEsCiAgICAgICAgICAgICAgICAgZmlsbCA9IE9yZGVyLAogICAgICAgICAgICAgICAgIGNvbG9yID0gUGh5bHVtKSkgKwogIGZhY2V0X3dyYXAofiBXRUVLICsgVFJFQVRNRU5ULAogICAgICAgICAgICAgc2NhbGVzID0gImZyZWVfeCIsCiAgICAgICAgICAgICBucm93ID0gMykgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgc2NhbGVfeF9kaXNjcmV0ZSgiIikgKwogIHNjYWxlX3lfY29udGludW91cyhleHBhbmQgPSBjKDAsIDApKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhqdXN0ID0gMSkpCmdncGxvdGx5KHAxKQpgYGAKCmBgYHtyIG1lYW5zX28sIGVjaG8gPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0V9CmxyYSA8LSByYV9tZWx0KHJhID0gcmFfbywKICAgICAgICAgICAgICAgc2FtcGxlcyA9IHNhbXBsZXMsCiAgICAgICAgICAgICAgIHNhbXBsZV9uYW1lID0gIlNBTVBMRV9OQU1FIikKCm11IDwtIGRhdGEudGFibGUoYWdncmVnYXRlKGxyYSRSQSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgYnkgPSBsaXN0KFdlZWsgPSBscmEkV0VFSywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyZWF0bWVudCA9IGxyYSRUUkVBVE1FTlQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBPcmRlciA9IGxyYSRPcmRlciksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIEZVTiA9ICJtZWFuIikpCm11WywgdG90YWwgOj0gc3VtKHgpLAogICBieSA9ICJPcmRlciJdCnVsIDwtIHVuaXF1ZShtdVssIGMoIk9yZGVyIiwgCiAgICAgICAgICAgICAgICAgICAgInRvdGFsIildKQp1bCA8LSB1bFtvcmRlcih0b3RhbCksXQptdSRPcmRlciA8LSBmYWN0b3IobXUkT3JkZXIsCiAgICAgICAgICAgICAgICAgICBsZXZlbCA9IHVsJE9yZGVyKQptdSR0b3RhbCA8LSBOVUxMCgpkYXRhdGFibGUobXUsCiAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLAogICAgICAgICAgY2FwdGlvbiA9ICJUYXhvbm9taWMgIGNvdW50IHRhYmxlIiwKICAgICAgICAgIGNsYXNzID0gImNlbGwtYm9yZGVyIHN0cmlwZSIsCiAgICAgICAgICBvcHRpb25zID0gbGlzdChzZWFyY2ggPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VMZW5ndGggPSBucm93KG11KSwKICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyID0gbGlzdChsaXN0KDMsICdkZXNjJykpKSkKYGBgCgpgYGB7ciBtZWFuc19vX3AwLCBmaWcud2lkdGggPSAxMCwgZmlnLmhlaWdodCA9IDV9CnAwIDwtIGdncGxvdChtdSwKICAgICAgICAgICAgIGFlcyh4ID0gV2VlaywKICAgICAgICAgICAgICAgICB5ID0geCwKICAgICAgICAgICAgICAgICBncm91cCA9IFRyZWF0bWVudCkpICsKICBmYWNldF93cmFwKH4gT3JkZXIsCiAgICAgICAgICAgICBzY2FsZSA9ICJmcmVlX3kiKSArCiAgZ2VvbV9saW5lKCkgKwogIGdlb21fcG9pbnQoYWVzKHNoYXBlID0gVHJlYXRtZW50LAogICAgICAgICAgICAgICAgIGNvbG9yID0gVHJlYXRtZW50KSwKICAgICAgICAgICAgIHNpemUgPSA1LAogICAgICAgICAgICAgYWxwaGEgPSAwLjUpCnByaW50KHAwKQpgYGAKCmBgYHtyIG1lYW5zX29fcDEsIGZpZy53aWR0aCA9IDEwLCBmaWcuaGVpZ2h0ID0gMTB9CnAxIDwtIGdncGxvdChtdSwKICAgICAgICAgICAgIGFlcyh4ID0geCwKICAgICAgICAgICAgICAgICB5ID0gT3JkZXIsCiAgICAgICAgICAgICAgICAgZmlsbCA9IFRyZWF0bWVudCwKICAgICAgICAgICAgICAgICBzaGFwZSA9IFdlZWspKSArCiAgIyBmYWNldF93cmFwKH4gU2V4LCBucm93ID0gMSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDMsCiAgICAgICAgICAgICBhbHBoYSA9IDAuNSkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDEsCiAgICAgICAgICAgICBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgc2NhbGVfeF9jb250aW51b3VzKCJSZWxhdGl2ZSBBYnVuZGFuY2UgKCUpIikKZ2dwbG90bHkocDEpCmBgYAoKIyBTZXNzaW9uIEluZm9ybWF0aW9uCmBgYHtyIGluZm8sZXZhbD1UUlVFfQpzZXNzaW9uSW5mbygpCmBgYA==